MacShell is a Unix-like command line interface for the Macintosh. It performs a limited imitation of the Unix C shell, and contains abbreviated versions of a set of Unix style file management, file finding, and content searching utilities. It also does a few Macintosh-specific functions, is scriptable, can execute compiled external code segments, and has a no-frills text editor built-in.
MacShell is free, courtesy of its author. It may not be sold in any form.
THE SHELL
The "Shell" component of the program has the following capabilities:
-Executes a set of built-in utilities.
-Executes code resources from external resource files.
-Performs file name substitution. (known to some as "globbing")
-Handles pipes.
-Performs redirection of standard I/O to and from files using the operators ">" and "<".
-Manages shell variables.
-Uses shell aliases.
-Runs scripts.
-Manages command history.
Among the many "shell" functions which MacShell does not support are the following:
-Flow control operators
-Launching of other applications
-Backquote substitution
-The append operator (>>)
BUILT-IN UTILITIES
This version performs approximations of the Unix utilities in the following list.
Note: to get more help with any command, type:
man commandname
command description
------- -----------
man get help
cd change directory
pwd print working directory
ls show the contents of a directory
cat concatenate
head copy the beginning of the input to the output
tail copy the end of the input to the output
cp copy files
mv move or rename files
rm remove files
mkdir make directory
grep content search utility
egrep content search using regular expressions
find find a file
more view a file
Additionally MacShell approximates some utilities which are built in to the Unix C-shell:
set set a shell variable
unset clear, or unset a shell variable
alias define a shell alias
unalias undefine a shell alias
echo report command line arguments on the output.
source execute a file as a script
rehash rebuild internal tables for 'path' and 'manpath'
which expand command name using the 'path' variable
history display the current command history list
exit quit MacShell
Finally, MacShell has a few special non Unix-like functions:
mem show heap statistics
free show free heap space
compact compact heap and report largest contiguous block
seg filter to segment long lines into shorter lines
xn filter out null characters from a stream
chtype change a Macintosh file type signature
chcreator change a Macintosh file creator signature
bintohex convert input to hexidecimal notation
For information about MacShell version history, invoke:
man version
DETAILS OF SHELL FUNCTIONS
The following "shell" functionality is supported by MacShell:
FILE NAME SUBSTITUTION
If MacShell finds the asterisk (*) in a command argument, it will attempt to substitute any string of characters (including the null string) in place of the asterisk to form one or more valid file names. This name (or these names) will be substituted into the command string prior to the execution of the command. Correct case must be observed when this mechanism is used. (Otherwise the Macintosh is case-insensitive.)
An asterisk may be hidden from MacShell by surrounding the argument that contains it in either double ("") or single ('') quotes. The argument will then be passed on to its command unaltered.
PIPE HANDLING
MacShell allows the output of one of its commands to be directed to the input of another by means of a pipe. The pipe character (|) is used to separate the two commands. (Note that MacShell's internal implementation of the pipe is quite different from the Unix implementation, even though they behave very similiarly)
REDIRECTION OF COMMAND INPUT AND OUTPUT TO AND FROM FILES
MacShell supports the use of I/O redirection operators "<" and ">." A filename which follows the input redirection symbol (<) on the command line will be opened and its contents will be used as input for the command. A filename which follows the output redirection operator (>) will be created if it does not exist (and overwritten if it does exist), and the output of the command will be written to it.
SHELL VARIABLES
MacShell is capable of managing shell variables. Shell variables are set and cleared with "set" and "unset." (See separate manual entries for set and unset). Set is also useful for displaying a list of currently defined variables and their values.
Once a shell variable is defined it's value may be used by the variable substitution mechanism to form part of a command line. Variable substitution is triggered by a '$' immediately preceeding the variable name. Variable substitution takes place before file name substitution. The entire variable (including the index, if used) may be surrounded by curly braces '{}' to avoid ambiguity if the name does not form a separate argument.
A shell variable may take a value of zero or more words. If the value consists of more than one word, the individual words may be selected by means of an index value in square brackets immediately following the variable name. The index value itself may be a shell variable since the variable substitution mechanism will evaluate index values first. Index values begin at 1. Supplying an index value of zero generates an error.
Special designators "$#" and "$?" can be used immediatly preceeding a shell variable name to cause the substitution mechanism to insert other information about shell variables. "$#varname" will be replaced with the number of words in the value of "varname," while "$?varname" will be replaced with "1" if the variable is set, and "0" otherwise.
SHELL VARIABLE EXAMPLES
Shell variables may be set in any of the following ways:
set a=1
set b=abc
set c
set d=()
set e=(1 2 3)
set e[1]=4
Some simple examples using the shell utility "echo" to report the results of variable substitution with the variables defined above:
echo $a
1
echo $e
(4 2 3)
echo $e[2]
2
echo $e[$a]
4
echo I'm${e[$a]}it
I'm4it
echo $#e
3
echo $?b
1
echo he's $?{b}for fun
he's 1for fun
echo $?z
0
COMMAND LINE EDITING
The 'erase line' command editing function is supported in the interactive window. This is driven by both Control-u and Command-u. This function is actually a 'cut' operation, so the erased line may be retrieved with a paste.
PATH AND MANPATH
MacShell supports special shell variables 'path' and 'manpath'.
These variables should be set, preferably in the MacShell configuration file, to contain names of directories (folders) which contain compiled code resources, and executable scripts. This will ease the process of invoking external commands and scripts, and reading associated manual entries.
The following are sample commands which might be used to set these shell variables:
set path=(MacHD:macshell:bin: MacHD:macshell:scripts: :)
set manpath=(MacHD:macshell:bin: :)
When a command is invoked that is not one of MacShell's built-in commands, MacShell will search the directories specified in 'path' for an appropriate executable file. A file is considered executable by MacShell if it meets one of the following two sets of conditions:
1. Its creator tag matches MacShell's, Its type tag is 'CODE', and it contains the appropriate resource type as detailed in the information referred to in the "external code resources" section below.
2. Its creator tag matches MacShell's, its type tag is 'TEXT', and the first two characters in its data fork match the Magic Cookie (see "Scripts" below).
When a manual entry is invoked (using the "man" utility) which is not one of the built-in entries, MacShell will search the directories specified in 'manpath' for a like-named executable file. MacShell will then attempt to locate an appropriate manual entry in the resource fork of this file.
If 'path' and/or 'manpath' are not set, the default path is the current directory (:). If the variables are set, the current directory should normally be included explicitly.
Two commands are provided to aid in the management of path and manpath:
1. rehash - Rebuild internal tables associated with path and manpath. One should use this utility after changing the contents of any directories specified therein.
2. which - Attempt to resolve a command name using the 'path' variable, just as it would be resolved when executed by the shell.
See separate manual entries for 'rehash' and 'which' for more complete information.
ALIAS SUBSTITUTION
The alias substitution mechanism provides a simple way for the user to change the meaning of a command, or to build a new command from existing commands. This mechanism substitutes a predefined string for the first word on a command line (or the first word on a line in a script). It is most convenient to define aliases in one's startup file 'macshell.rc', so that they will be applied automatically to each session.
Aliases are defined by the use of the built-in command 'alias' and undefined with 'unalias'. See separate manual entries for more details on the use of these two commands.
If the first word on a command line is found to match a defined alias, the substitution mechanism replaces it with the list of words contained in the alias definition. It then copys remaining arguments, from the second word of the command to the end, to the new argument list, without making any changes to them. The new list of arguments is then passed to the variable substitutuion routine, and the file name substitution (globbing) routine, before being executed.
MacShell's alias substitution capabilities are limited in the following ways (compared to some unix shells):
- Alias substitution is not carried out recursively.
- It is not possible for an alias definition to contain arguments
which are replaced at runtime.
COMMAND HISTORY
Command history is a mechanism intended to make it easier for commands invoked by means of the interactive window to be repeated. Each command invoked is stored in a special list. Once in the list, a command can be re-executed by means of a variety of simple keyboard shortcuts
MacShell manages a fixed-length command history list. Items in the list are given index numbers beginning at 1. After the list reaches its maximum length, new commands added to the list cause commands to be removed from the beginning of the list. The numbering continues on indefinately.
The history list is currently limited to 256 elements in length.
Only commands typed to the interactive window are included in the list. Commands invoked via shell script are ignored by the history mechanism.
The contents of the list can be examined by means of the command 'history'. (See separate manual entry for more information).
Items in the history list can be re-executed in a variety of ways:
1. Up-arrow and down-arrow cause the previous and next items from the history list to be pasted directly on the command line.
2. If the special character '!' is found in a command line, the shell will attempt to parse it as a history expression of one of the below listed types, and to replace the expression with the corresponding item from the history list. Recognized types of history expressions beginning with '!' are:
a). '!!' -- represents the previous command.
b). '!n' -- where n is an integer, represents the item in the
history list with index number n.
c). '!str' -- where 'str' represents an arbitrary string, is replaced
by the most recent item in the history list beginning with the
string.
This type of history substitution is carried out prior to all other forms of cammand line processing.
SCRIPTS
MacShell includes a built-in utilitiy which will open a file and execute each line as a MacShell command. No control flow operators are supported at this time. (For more information see the manual entry for "source").
MacShell can also execute certain scripts without using the "source" utility. In order to qualify for this treatment, a script must begin with the two character sequence '#!'. This sequence is referred to as the "Magic Cookie". The Magic Cookie is equivalent to an executable mode bit in the unix world.
In addition, MacShell can execute certain files at launch time. For more information, see the headings "startup files" and "configuration file" in this entry.
STANDARD INPUT AND STANDARD OUTPUT
Standard input and output is a means by which many Unix utilities interact with the outside world. MacShell supports this paradigm to some extent.
Standard input may be directed to some MacShell commands from a file with the input redirection operator (<), or from the output of the preceeding command using a pipe (|).
None of MacShell's built-in utilities use the interactive window as standard input. However, there are now a few external code resources in existance which do. The 'standard' character used to terminate interactive input is Control-d (and perhaps additionally Option-d). It is my hope that authors of external code will observe this convention.
The default standard output for most MacShell commands is the interactive window. If the pipe operator (|) is used, standard output is routed to the command which follows. If the output redirection operator (>) is present, standard output is directed to the file whose name follows the operator.
ABOUT MACINTOSH PATH NAMES
According to Macintosh convention, the colon (:) is used in path names to separate volume, folder and file names. The following rules should be noted:
-Absolute path names do not begin with a colon, for example:
MyDisk:MyFolder:MyFile
-When an absolute path name consists of only one name, it must end in a colon, for example:
MyDisk:
-Relative path names must begin with a colon, except in the case where they consist of only one name:
MyFolder
:MyFolder:MyFile
-Consecutive colons may be used in a path name to represent a move up the directory tree. Two colons (::) would represent the parent of the working directory, three would represent the parent of the parent, and so on.
CASE SENSITIVITY
The Macintosh finder and toolbox are not case sensitive. In other words, as far as the Macintosh is concerned, "Filename" is the same as "filename." Therefore it is not necessary to observe case when using MacShell to interface directly with the Macintosh file system.
However, MacShell's file name substitution function IS case sensitive. If asterisks are used as wildcard characters in file names, case must be observed in the remainder of the name (this should be changed).
NAME COMPLETION
When used interactively MacShell will attempt to complete a file name when the escape key (by default) is typed. The user must first type enough characters to form a unique beginning of a file name. The mechanism will add characters until a point of ambiguity is reached, or until the file name is completed. If the file name is not completed, the mechanism will cause a system beep.
Since Macintosh file names may include embedded spaces, and since these names must be quoted in MacShell, the name completion function will ignore a quote found at the beginning of a word. This will allow most file names with embedded spaces to be quoted and automatically completed with ease.
The wildcard character "*" is not recognized by the file name completion mechanism.
Those using older keyboards which don't have the escape key, and those who prefer the behavior of other shells which use the tab key to trigger name completion, may alter the default behavior by setting or unsetting two special shell variables:
- Setting a variable called "remapesc" will cause the backquote key in the upper left corner of the old Mac Plus keyboard to be used to trigger name completion
- Setting a variable named "tabnc" will cause the tab key to be used to trigger the name completion mechanism. This variable takes precedence over "remapesc" if both are set.
STARTUP FILES
MacShell treats its startup files just as most other applications do: The files are opened immediately after MacShell is launched. However, it is also possible to cause MacShell to treat startup files as scripts to be executed. A MacShell file will be executed on startup if the first two characters in the file are "#!".(This string is referred to as the Magic Cookie).
Note that a file with the magic cookie will not be executed when it is opened from the File menu.
CONFIGURATION FILE
If a file called "macshell.rc" is found in the same directory with the MacShell application itself, this file will be opened and executed as a script when MacShell is launched.
INVOKING EXTERNAL CODE RESOURCES FROM MACSHELL
It's possible to write code in a language like C or Pascal, and compile it into code resources which can be called directly by MacShell. I have some sample code (in C) demonstrating how to do this. This information is currently available via anonymous ftp from:
If you do any generally useful work with this source (modifications, extensions, bug fixes), I would be interested in receiving your patches for possible inclusion in future (free) versions of MacShell.
MACSHELL WEB PAGE
A page of information about MacShell, including pointers to the latest executable, source, and code resource packages is available at: